<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .box1{width: 100px;height:100px;background: red;position: absolute;left:0;top:0;}
        .box2{width: 100px;height:100px;background: green;position: absolute;left:0;top:100px;}
    </style>
</head>
<body>
    <div class="box1"></div>
    <div class="box2"></div>
</body>
<script>

    const obox1 = document.querySelector(".box1");
    const obox2 = document.querySelector(".box2");

    obox1.onclick = function(){

        move(obox1, {
            left: 400
        }, function(){
            console.log("12123")
        });

    }

    obox2.onclick = function(){

        move(obox2, {
            left: 400
        }, function(){
            console.log("12123")
        });

    }

    // 问题：
    // 当操作多属性同时运动时（每个属性的目标不一致），不能在有一个属性到目标后，清除计时器
    // 因为有可能其他属性还没到目标

    // 思考：
    // 所有属性都到目标了，一定会清计时器
    // 只要有一个属性没到目标，一定不能清计时器
        // now != target

    // 解决：
    // 默认，立即清计时器
    // 如果有属性没到目标，改变默认值
    // 如果没有属性没到目标，不改变默认值


    function move(ele, obj, cb){
        // 1. 开启之前的清除
        clearInterval(ele.abc);
        // 2. 开启计时器
        ele.abc = setInterval(()=>{
            // 3. 设置计时器要清除的标志：默认立即清除
            let flag = true;
            // 4. 遍历对象，获取到要操作的属性和对应的目标
            for(let i in obj){
                // 5. 获取当前值
                let now = parseInt(getStyle(ele, i));
                // 6. 计算步长（用来实现缓冲）
                let speed = (obj[i] - now)/10
                speed = speed < 0 ? Math.floor(speed) : Math.ceil(speed);
                // 7. 计算元素数据（当前 + 步长），并设置到元素
                ele.style[i] = now + speed + "px";
                // 8. 只要有一个属性没到目标，保证不能清计时器
                if(now !== obj[i]) flag = false;
            }
            // 9. 等遍历结束后，根据清除计时器的标志，决定是否清除计时器
            if(flag){
                clearInterval(ele.abc);
                // 10. 根据是否传入运动结束后要执行的功能，决定是否执行
                if(cb) cb();
            }
        }, 30);
    }

    // 获取当前样式的兼容封装
    function getStyle(ele, attr){
        return ele.currentStyle ? ele.currentStyle[attr] : getComputedStyle(ele)[attr];
    }
    
</script>
</html>